﻿using Infrastructure.Centers;
using Infrastructure.Http;
using Infrastructure.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Minio;
using Newtonsoft.Json;

namespace Infrastructure.Extensions
{
    public static class ServiceCollectionExtensions
    {

        // Method to configure MinIO
        public static IServiceCollection AddMinio(this IServiceCollection services, IConfiguration configuration)
        {
            var minioSettingsSection = configuration.GetSection("Minio");
            var endpoint = minioSettingsSection["Endpoint"];
            var accessKey = minioSettingsSection["AccessKey"];
            var secretKey = minioSettingsSection["SecretKey"];
            var minioClient = new MinioClient()
                .WithEndpoint(endpoint)
                .WithCredentials(accessKey, secretKey)
                .Build();

            services.AddSingleton(minioClient);

            return services;
        }
        // 扩展方法，用于添加并配置FileCenter服务
        public static void AddFileCenter(this IServiceCollection services, Action<FileCenterOption> setupAction)
        {
            // 如果传入的配置委托为空，则抛出异常
            if (setupAction == null)
            {
                throw new ArgumentNullException(nameof(setupAction));
            }

            // 创建FileCenter配置实例，并通过委托进行配置
            FileCenterOption optFileCenter = new FileCenterOption();
            setupAction(optFileCenter);

            // 获取FileCenter信息，发送HttpPost请求到配置的URL
            string responseText = HttpHelper.HttpPost(optFileCenter.FileCenterUrl + "/" +
                optFileCenter.GetMinioUrl, JsonConvert.SerializeObject(new MinioInfoReq
                {
                    AppId = optFileCenter.AppId,
                    AccessKey = optFileCenter.AccessKey
                }));

            // 如果返回的文本非空则处理，否则抛出异常
            if (!string.IsNullOrWhiteSpace(responseText))
            {
                // 反序列化返回结果
                ApiResult apiResult = JsonConvert.DeserializeObject<ApiResult>(responseText);
                // 如果请求未成功，抛出异常
                if (!apiResult.IsSuccess)
                {
                    throw new Exception("查询文件中心失败，请检查文件中心:" + responseText);
                }

                // 反序列化返回的Minio信息
                MinioInfoRes dtoMinioInfoRes = JsonConvert.DeserializeObject<MinioInfoRes>(apiResult.Data.ToString());
                optFileCenter.MinioUrl = dtoMinioInfoRes.MinioUrl;
                optFileCenter.Username = dtoMinioInfoRes.MinioUsername;
                optFileCenter.Password = dtoMinioInfoRes.MinioPassword;

                // 配置Kestrel服务器选项限制最大请求体大小
                services.Configure<KestrelServerOptions>(options =>
                {
                    options.Limits.MaxRequestBodySize = optFileCenter.MaxSizeMBPerFile * 1024 * 1024;
                });

                // 配置表单选项限制最大多部分体长度
                services.Configure<FormOptions>(x =>
                {
                    x.MultipartBodyLengthLimit = optFileCenter.MaxSizeMBPerFile * 1024 * 1024;
                });

                // 注册Minio客户端服务
                services.AddTransient(serviceProvider => new MinioClient()
                    .WithEndpoint(optFileCenter.MinioUrl)
                    .WithCredentials(optFileCenter.Username, optFileCenter.Password)
                    .Build());

                // 注册文件中心服务（单例）
                services.AddSingleton<IFileCenter>(serviceProvider => new FileCenter(
                    serviceProvider.GetRequiredService<MinioClient>(),
                    optFileCenter,
                    serviceProvider.GetRequiredService<IHttpContextAccessor>()
                ));
                return;
            }

            // 请求未返回任何内容，抛出异常
            throw new Exception("查询文件中心失败，请检查文件中心：结果为空");
        }
        public static void AddSideCar(this IServiceCollection services, Action<SideCarOption> setupAction)
        {
            if (setupAction == null)
            {
                throw new ArgumentNullException("setupAction");
            }

            services.Configure(setupAction);
        }


    }
}
